﻿using GxIAPINET;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 相机调用
{
    public partial class MainForm : Form
    {
        #region 大恒字段
        bool m_bIsOpen = false;                                  ///< 相机打开标识 
        bool m_bIsSnap = false;                                  ///< 相机开始采集标识
        bool m_bColorFilter = false;                             ///< 标识是否支持Bayer格式
        bool m_bAwbLampHouse = false;                            ///< 标示是否支持光源选择
        bool m_bWhiteAutoSelectedIndex = true;                   ///< 白平衡列表框转换标志
        IGXFactory m_objIGXFactory = null;                       ///< Factory对像
        IGXDevice m_objIGXDevice = null;                         ///< 设备对像
        IGXStream m_objIGXStream = null;                         ///< 流对像
        IGXFeatureControl m_objIGXFeatureControl = null;         ///< 远端设备属性控制器对像
        IGXFeatureControl m_objIGXStreamFeatureControl = null;   ///< 流层属性控制器对象
        IImageProcessConfig m_objCfg = null;                     ///< 图像配置参数对象

        GxBitmap m_objGxBitmap = null;                           ///< 图像显示类对象
        string m_strPixelColorFilter = null;                     ///< Bayer格式
        string m_strBalanceWhiteAutoValue = "Off";               ///< 自动白平衡当前的值
        bool m_bEnableColorCorrect = false;                      ///< 颜色校正使能标志位
        bool m_bEnableGamma = false;                             ///< Gamma使能标志位
        bool m_bEnableSharpness = false;                         ///< 锐化使能标志位 
        bool m_bEnableAutoWhite = false;                         ///< 自动白平衡使能标志位
        bool m_bEnableAwbLight = false;                          ///< 自动白平衡光源使能标志位
        bool m_bEnableDenoise = false;                           ///< 图像降噪使能标志位
        bool m_bEnableSaturation = false;                        ///< 饱和度使能标志位
        bool m_bEnumDevices = false;                             ///< 是否枚举到设备标志位
        List<IGXDeviceInfo> m_listGXDeviceInfo;                  ///< 存放枚举到的设备的容器
        #endregion
        #region 自写字段
        IBaseData objIBaseData = null;                           ///< 图像基础数据 
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }

        #region 自写方法
        /// <summary>
        /// 打开设备
        /// 目前默认打开第一个设备，有定制业务的话需要修改代码
        /// </summary>
        public void OpenDevice()
        {
            try
            {
                //关闭流
                __CloseStream();
                // 如果设备已经打开则关闭，保证相机在初始化出错情况下能再次打开
                __CloseDevice();

                //打开相机，默认打开第一个
                m_objIGXDevice = m_objIGXFactory.OpenDeviceBySN(m_listGXDeviceInfo[0].GetSN(), GX_ACCESS_MODE.GX_ACCESS_EXCLUSIVE);
                m_objIGXFeatureControl = m_objIGXDevice.GetRemoteFeatureControl();

                __InitDevice();

                //打开流
                if (null != m_objIGXDevice)
                {
                    m_objIGXStream = m_objIGXDevice.OpenStream(0);
                    m_objIGXStreamFeatureControl = m_objIGXStream.GetFeatureControl();
                }

                // 建议用户在打开网络相机之后，根据当前网络环境设置相机的流通道包长值，
                // 以提高网络相机的采集性能,设置方法参考以下代码。
                GX_DEVICE_CLASS_LIST objDeviceClass = m_objIGXDevice.GetDeviceInfo().GetDeviceClass();
                if (GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV == objDeviceClass)
                {
                    // 判断设备是否支持流通道数据包功能
                    if (true == m_objIGXFeatureControl.IsImplemented("GevSCPSPacketSize"))
                    {
                        // 获取当前网络环境的最优包长值
                        uint nPacketSize = m_objIGXStream.GetOptimalPacketSize();
                        // 将最优包长值设置为当前设备的流通道包长值
                        m_objIGXFeatureControl.GetIntFeature("GevSCPSPacketSize").SetValue(nPacketSize);
                    }
                }

                m_objCfg = m_objIGXDevice.CreateImageProcessConfig();


                // 初始化UI界面控件
                __InitUI();

                m_objGxBitmap = new GxBitmap(m_objIGXDevice, pictureBox);

                // 更新设备打开标识
                m_bIsOpen = true;
                m_bEnumDevices = false;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        public void CloseDevice()
        {
            try
            {
                // 停止采集关闭设备、关闭流
                __CloseAll();
                m_bEnumDevices = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 开始采集
        /// </summary>
        public void StartDevice()
        {
            try
            {
                if (null != m_objIGXStreamFeatureControl)
                {
                    try
                    {
                        //设置流层Buffer处理模式为OldestFirst
                        m_objIGXStreamFeatureControl.GetEnumFeature("StreamBufferHandlingMode").SetValue("OldestFirst");
                    }
                    catch (Exception)
                    {
                    }
                }

                //开启采集流通道
                if (null != m_objIGXStream)
                {
                    //RegisterCaptureCallback第一个参数属于用户自定参数(类型必须为引用
                    //类型)，若用户想用这个参数可以在委托函数中进行使用
                    m_objIGXStream.RegisterCaptureCallback(this, __OnFrameCallbackFun);
                    m_objIGXStream.StartGrab();
                }

                //发送开采命令
                if (null != m_objIGXFeatureControl)
                {
                    m_objIGXFeatureControl.GetCommandFeature("AcquisitionStart").Execute();
                }
                m_bIsSnap = true;
                m_bEnumDevices = false;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 停止采集
        /// </summary>
        public void StopDevice()
        {
            try
            {
                //发送停采命令
                if (null != m_objIGXFeatureControl)
                {
                    m_objIGXFeatureControl.GetCommandFeature("AcquisitionStop").Execute();
                }

                //关闭采集流通道
                if (null != m_objIGXStream)
                {
                    m_objIGXStream.StopGrab();
                    //注销采集回调函数
                    m_objIGXStream.UnregisterCaptureCallback();
                }

                m_bIsSnap = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        #endregion

        #region 大恒方法
        /// <summary>
        /// 设备打开后初始化界面
        /// </summary>
        private void __InitUI()
        {

            if (null != m_objCfg)
            {
                if (m_bColorFilter)
                {
                    //获取白平衡当前的值
                    bool bIsImplemented = false;             //是否支持
                    bool bIsReadable = false;                //是否可读
                    // 获取是否支持
                    if (null != m_objIGXFeatureControl)
                    {
                        bIsImplemented = m_objIGXFeatureControl.IsImplemented("BalanceWhiteAuto");
                        bIsReadable = m_objIGXFeatureControl.IsReadable("BalanceWhiteAuto");
                        if (bIsImplemented)
                        {
                            if (bIsReadable)
                            {
                                //获取当前功能值
                                m_strBalanceWhiteAutoValue = m_objIGXFeatureControl.GetEnumFeature("BalanceWhiteAuto").GetValue();
                            }
                        }
                    }
                    m_bEnableAutoWhite = false;
                    m_bEnableAwbLight = false;
                    m_bEnableColorCorrect = false;
                    m_bEnableDenoise = false;
                    m_bEnableSaturation = false;
                }
                else
                {
                    // 打开的是黑白相机
                    m_bEnableAutoWhite = true;
                    m_bEnableAwbLight = true;
                    m_bEnableColorCorrect = true;
                    m_bEnableDenoise = true;
                    m_bEnableSaturation = true;

                }
            }

        }

        /// <summary>
        /// 枚举型功能ComBox界面初始化
        /// </summary>
        /// <param name="cbEnum">ComboBox控件名称</param>
        /// <param name="strFeatureName">枚举型功能名称</param>
        /// <param name="objIGXFeatureControl">属性控制器对像</param>
        /// <param name="bIsImplemented">是否支持</param>
        private void __InitEnumComBoxUI(ComboBox cbEnum, string strFeatureName, IGXFeatureControl objIGXFeatureControl, ref bool bIsImplemented)
        {
            string strValue = "";                   //当前选择项
            List<string> list = new List<string>();   //Combox将要填入的列表
            bool bIsReadable = false;                //是否可读
            // 获取是否支持
            if (null != objIGXFeatureControl)
            {

                bIsImplemented = objIGXFeatureControl.IsImplemented(strFeatureName);
                // 如果不支持则直接返回
                if (!bIsImplemented)
                {
                    return;
                }

                bIsReadable = objIGXFeatureControl.IsReadable(strFeatureName);

                if (bIsReadable)
                {
                    list.AddRange(objIGXFeatureControl.GetEnumFeature(strFeatureName).GetEnumEntryList());
                    //获取当前功能值
                    strValue = objIGXFeatureControl.GetEnumFeature(strFeatureName).GetValue();
                }

            }

            //清空组合框并更新数据到窗体
            cbEnum.Items.Clear();
            foreach (string str in list)
            {
                cbEnum.Items.Add(str);
            }

            //获得相机值和枚举到值进行比较，刷新对话框
            for (int i = 0; i < cbEnum.Items.Count; i++)
            {
                string strTemp = cbEnum.Items[i].ToString();
                if (strTemp == strValue)
                {
                    cbEnum.SelectedIndex = i;
                    break;
                }
            }
        }

        /// <summary>
        /// 相机初始化
        /// </summary>
        private void __InitDevice()
        {

            if (null != m_objIGXFeatureControl)
            {
                //设置采集模式连续采集
                m_objIGXFeatureControl.GetEnumFeature("AcquisitionMode").SetValue("Continuous");

                //设置触发模式为关
                m_objIGXFeatureControl.GetEnumFeature("TriggerMode").SetValue("Off");

                // 判断相机是否支持bayer格式
                m_bColorFilter = m_objIGXFeatureControl.IsImplemented("PixelColorFilter");

                // 获取图像Bayer格式
                if (m_bColorFilter)
                {
                    m_strPixelColorFilter = m_objIGXFeatureControl.GetEnumFeature("PixelColorFilter").GetValue();
                }

                // 判断相机是否支持白平衡光源选择
                m_bAwbLampHouse = m_objIGXFeatureControl.IsImplemented("AWBLampHouse");

                __IsEnableDeviceColorCorrect();
                __IsEnableDeviceGamma();
                __IsEnableDeviceSharpness();
            }
        }

        /// <summary>
        /// 关闭流
        /// </summary>
        private void __CloseStream()
        {
            try
            {
                //关闭流
                if (null != m_objIGXStream)
                {
                    m_objIGXStream.Close();
                    m_objIGXStream = null;
                    m_objIGXStreamFeatureControl = null;
                }
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        private void __CloseDevice()
        {
            try
            {
                //关闭设备
                if (null != m_objIGXDevice)
                {
                    m_objIGXDevice.Close();
                    m_objIGXDevice = null;
                }
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 停止采集关闭设备、关闭流
        /// </summary>
        private void __CloseAll()
        {
            try
            {
                //如果未停采则先停止采集
                if (m_bIsSnap)
                {
                    if (null != m_objIGXFeatureControl)
                    {
                        m_objIGXFeatureControl.GetCommandFeature("AcquisitionStop").Execute();
                        m_objIGXFeatureControl = null;
                    }
                }
            }
            catch (Exception)
            {

            }

            m_bIsSnap = false;

            try
            {
                //停止流通道、注销采集回调和关闭流
                if (null != m_objIGXStream)
                {
                    m_objIGXStream.StopGrab();
                    //注销采集回调函数
                    m_objIGXStream.UnregisterCaptureCallback();
                    m_objIGXStream.Close();
                    m_objIGXStream = null;
                    m_objIGXStreamFeatureControl = null;
                }

            }
            catch (Exception)
            {

            }

            //关闭设备
            __CloseDevice();
            m_bIsOpen = false;
        }

        /// <summary>
        /// 初始化选择设备下拉框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void __InitDeviceCombox()
        {
            try
            {
                m_listGXDeviceInfo = new List<IGXDeviceInfo>();
                m_objIGXFactory.UpdateDeviceList(200, m_listGXDeviceInfo);

                // 判断当前连接设备个数
                if (m_listGXDeviceInfo.Count <= 0)
                {
                    MessageBox.Show("没有枚举到设备，请插入相机并重启程序！");
                    m_bEnumDevices = false;
                    return;
                }
                else
                {
                    m_bEnumDevices = true;
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 采集事件的委托函数
        /// </summary>
        /// <param name="objUserParam">用户私有参数</param>
        /// <param name="objIFrameData">图像信息对象</param>
        private void __OnFrameCallbackFun(object objUserParam, IFrameData objIFrameData)
        {
            try
            {
                MainForm objGxImageProcess = objUserParam as MainForm;
                objIBaseData = objIFrameData;
                objGxImageProcess.ShowImageProcess(objIFrameData);
            }
            catch (Exception)
            {

            }
        }

        /// <summary>
        /// 通过GX_PIXEL_FORMAT_ENTRY获取最优Bit位
        /// </summary>
        /// <param name="em">图像数据格式</param>
        /// <returns>最优Bit位</returns>
        private GX_VALID_BIT_LIST __GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry)
        {
            GX_VALID_BIT_LIST emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
            switch (emPixelFormatEntry)
            {
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR8:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG8:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB8:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG8:
                    {
                        emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
                        break;
                    }
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10:
                    {
                        emValidBits = GX_VALID_BIT_LIST.GX_BIT_2_9;
                        break;
                    }
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12:
                    {
                        emValidBits = GX_VALID_BIT_LIST.GX_BIT_4_11;
                        break;
                    }
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14:
                    {
                        //暂时没有这样的数据格式待升级
                        break;
                    }
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO16:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR16:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG16:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB16:
                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG16:
                    {
                        //暂时没有这样的数据格式待升级
                        break;
                    }
                default:
                    break;
            }
            return emValidBits;
        }

        /// <summary>
        ///  用于图像处理后并显示图像
        /// </summary>
        /// <param name="objIBaseData">图像信息对象</param>
        public void ShowImageProcess(IBaseData objIBaseData)
        {
            GX_VALID_BIT_LIST emValidBits = GX_VALID_BIT_LIST.GX_BIT_0_7;
            try
            {
                if (null != m_objCfg)
                {
                    emValidBits = __GetBestValudBit(objIBaseData.GetPixelFormat());
                    m_objCfg.SetValidBit(emValidBits);
                    ////首先配置图像处理参数以免造成图像处理耗时刷先界面卡死
                    objIBaseData.ImageProcess(m_objCfg);
                }
            }
            catch (Exception)
            {

            }

            if (null != m_objCfg)
            {
                m_objGxBitmap.ShowImageProcess(m_objCfg, objIBaseData);
            }
        }

        /// <summary>
        /// 对枚举型变量按照功能名称设置值
        /// </summary>
        /// <param name="strFeatureName">枚举功能名称</param>
        /// <param name="strValue">功能的值</param>
        /// <param name="objIGXFeatureControl">属性控制器对像</param>
        private void __SetEnumValue(string strFeatureName, string strValue, IGXFeatureControl objIGXFeatureControl)
        {
            if (null != objIGXFeatureControl)
            {
                //设置当前功能值
                objIGXFeatureControl.GetEnumFeature(strFeatureName).SetValue(strValue);
            }
        }

        /// <summary>
        /// 获取设备是否打开颜色校正
        /// </summary>
        private void __IsEnableDeviceColorCorrect()
        {
            m_bEnableColorCorrect = false;
            bool bIsImplement = m_objIGXFeatureControl.IsImplemented("ColorTransformationEnable");
            if (false == bIsImplement)
            {
                return;
            }
            IBoolFeature pBoolFeature = m_objIGXFeatureControl.GetBoolFeature("ColorTransformationEnable");
            m_bEnableColorCorrect = pBoolFeature.GetValue();
        }

        /// <summary>
        /// 获取设备是否打开Gamma使能
        /// </summary>
        private void __IsEnableDeviceGamma()
        {
            m_bEnableGamma = false;
            bool bIsImplement = m_objIGXFeatureControl.IsImplemented("GammaEnable");
            if (false == bIsImplement)
            {
                return;
            }

            IBoolFeature pBoolFeature = m_objIGXFeatureControl.GetBoolFeature("GammaEnable");

            m_bEnableGamma = pBoolFeature.GetValue();
        }

        /// <summary>
        /// 获取设备是否打开锐化使能
        /// </summary>
        private void __IsEnableDeviceSharpness()
        {
            m_bEnableSharpness = false;
            bool bIsImplement = m_objIGXFeatureControl.IsImplemented("SharpnessMode");
            if (false == bIsImplement)
            {
                return;
            }

            IEnumFeature pEnumFeature = m_objIGXFeatureControl.GetEnumFeature("SharpnessMode");
            string strValue = pEnumFeature.GetValue();

            if (true == strValue.Equals("Off"))
            {
                m_bEnableSharpness = false;
            }
            else if (true == strValue.Equals("On"))
            {
                m_bEnableSharpness = true;
            }
        }
        #endregion

        #region 必备事件
        /// <summary>
        /// 页面加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                m_objIGXFactory = IGXFactory.GetInstance();
                m_objIGXFactory.Init();
                __InitDeviceCombox();

                OpenDevice();
                StartDevice();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 页面卸载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                // 停止采集、关闭流、关闭设备
                __CloseAll();

                //反初始化
                if (null != m_objIGXFactory)
                {
                    m_objIGXFactory.Uninit();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 页面卸载确认
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("你确定关闭程序吗", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (result != DialogResult.OK)
            {
                e.Cancel = true;
            }
        }
        #endregion

        /// <summary>
        /// 方便测试截取图片功能
        /// 点击一下保存一下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pictureBox_Click(object sender, EventArgs e)
        {
            try
            {
                //自定义目录为SaveImages
                string directory = "SaveImages";
                //目录不存在则先创建
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
                //以时间为名，尽量不重复
                string filepath = $"{directory}/{DateTime.Now:yyyyMMddHHmmssff}.jpg";
                //GxBitmap对象非空则开始保存，后缀为jpg
                m_objGxBitmap?.SaveJpg(objIBaseData, filepath);
                Debug.WriteLine($"{filepath} -- 保存完毕！");
            }
            catch { }
        }
    }
}
